﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Markup;
using System.Collections;

namespace DefensiveShield
{
    //=================================================================================================================================
    //==================================================================================================== OS =========================
    //=================================================================================================================================
    public static partial class OS
    {
        //---------------------------------------------------------------------------------------------------------------------------------
        //---------------------------------------------------------------------------------------------------- OS INITIALIZATION ----------
        //---------------------------------------------------------------------------------------------------------------------------------
        /**
            @brief Данная функция инициализирует основной класс OS
             * 
             * Её необходимо выполнять в начале каждого запуска продукта.
             * 
            @return Код ошибки, при её наличии
        */
        public static ErrorCodes InitializeOS()
        {
            try
            {
                bool createdNew;
                _mutexForSingleApplicationInstance = new Mutex(true, "ApplicationMutex", out createdNew);
                if (!createdNew)
                {
                    LogMessage("System", "Can not start more then 2 instances of application.");
                    return ErrorCodes.ErrorStartingSeveralApplicationInstances;
                }

                Users = new Dictionary<string, UserPassport>();
                Files = new Dictionary<string, FilePassport>();
                FileIntegrity = new Dictionary<string, string>();
                DateLastIntegrityCheck = new DateTime(2014, 11, 11, 12, 0, 0);
                Sessions = new List<OsSession>();

                // Creating baseDirectory in ApplicationData folder for user
                // string baseDirectory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Defensive Shield";
                // Directory.CreateDirectory(baseDirectory);

                var baseDirectory = Directory.GetCurrentDirectory();

                AdministratorName = null;
                _configurationFileName = baseDirectory + "\\DefensiveShieldSettings.xml";
                _logFullFileName = baseDirectory + "\\DefensiveShield.log";
                GlobalKey = "This is global key kiddie!!!";

                var retVal = ConnectCryptoDll();
                if (retVal != ErrorCodes.NoError)
                {
                    // If there is error in ConnectCryptoDll, than you will have problems with logging anyway
                    // The system must be stopped
                    return retVal;
                }
                
                retVal = ReadConfigurationFromFile(_configurationFileName);
                if (retVal != ErrorCodes.NoError)
                    LogMessage("", "Error reading configuration file. System will start as it is its installation.", _configurationFileName);

                LogMessage("", "Successful system initialization");
                return ErrorCodes.NoError;
            }
            catch (Exception except)
            {
                LogMessage("", "Error in Initializing OS. Exception: " + except.Message);
                return ErrorCodes.UnknownError;
            }
        }

        //---------------------------------------------------------------------------------------------------------------------------------
        //---------------------------------------------------------------------------------------------------- CREATE SESSION -------------
        //---------------------------------------------------------------------------------------------------------------------------------
        /**
            @brief Данная функция создаёт новую сессию и возвращает её
             * 
             * Сессия сохраняется в список сессий, откуда с ними потом можно оперировать
             * 
            @return ссылка на созданный OsSession
            @return null - в случае ошибки
        */
        public static OsSession CreateOsSession()
        {
            try
            {
                var osSession = new OsSession();
                Sessions.Add(osSession);

                LogMessage("", "Successful Os Session creation.");
                return osSession;
            }
            catch (Exception except)
            {
                LogMessage("", "Error in creating Os Session. Exception: " + except.Message);
                return null;
            }
        }

        //---------------------------------------------------------------------------------------------------------------------------------
        //---------------------------------------------------------------------------------------------------- DELETE OS SESSION ----------
        //---------------------------------------------------------------------------------------------------------------------------------
        /**
            @brief Данная функция удаляет указанную пользовательскую сессию
            @return Код ошибки, при её наличии
        */
        public static ErrorCodes DeleteOsSession(OsSession osSession)
        {
            try
            {
                if (!Sessions.Remove(osSession))
                {
                    LogMessage(osSession.UserName, "Error closing os session, no such session.");
                    return ErrorCodes.ErrorInDeletingOsSession;
                }

                LogMessage(osSession.UserName, "Successful session closing.");
                return ErrorCodes.NoError;
            }
            catch (Exception except)
            {
                LogMessage(osSession.UserName, "Error closing Os Session. Exception: " + except.Message);
                return ErrorCodes.UnknownError;
            }
        }

        //---------------------------------------------------------------------------------------------------------------------------------
        //---------------------------------------------------------------------------------------------------- SAVING OS SETTINGS ---------
        //---------------------------------------------------------------------------------------------------------------------------------
        /**
            @brief функция, сохраняющая всю служебную информацию в системе в некоторый шифрованный файл
            @return Код ошибки, при её наличии
        */
        public static ErrorCodes ShutdownOS()
        {
            var retVal = WriteConfigurationToFile(_configurationFileName);
            if (retVal != ErrorCodes.NoError)
            {
                LogMessage("", "Error saving configurations.", _configurationFileName);
                return retVal;
            }

            retVal = DisconnectCryptoDll();
            if (retVal != ErrorCodes.NoError)
            {
                LogMessage("", "Error disconnecting from CryptoDll.");
            }

            // Temporary for developing time:
            RemoveLog();

            Users.Clear();
            Files.Clear();
            Sessions.Clear();
            AdministratorName = "";
            FileIntegrity.Clear();
            GlobalKey = "";
            _configurationFileName = "";
            _logFullFileName = "";

            LogMessage("", "System shoot down.");
            return ErrorCodes.NoError;
        }
    }
}
